package com.apes.fn.scm.retailOrder.service.account;

import com.apes.fn.scm.retailOrder.model.RetailOrder;
import com.apes.fn.scm.retailOrder.model.RetailOrderItem;
import com.apes.fn.scm.retailOrder.repository.RetailOrderRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.util.LogicalUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.account.account.model.InventoryBatch;
import com.apes.scm.account.account.service.InventoryService;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.sal.saleOrder.SaleOrder;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.model.VoucherInventory;
import com.apes.scm.voucher.model.VoucherItem;
import com.apes.scm.voucher.repository.VoucherInventoryRepository;
import com.apes.scm.voucher.service.VoucherType;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 回填批次号与供应商使用
 *
 * @Author wuq
 * @Date 2021-7-23
 */
public abstract class BackBatchAndSupplierService extends DomainService implements RetailVoucher {

    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private VoucherInventoryRepository voucherInventoryRepository;

    protected Dept getDept(PartyRole company) {
        return SpringManager.getBean(DeptRepository.class)
                .findAll(JpaDsl.toCriteriaByEq("company", company, "innerTag", true, "deptType.id", "000006"))
                .stream().findFirst().orElseThrow(() -> new RuntimeException("没有找到内定标记部门，请先定义！公司：：" + company.getId()));
    }

    /**
     * 冻结批次数
     *
     * @param voucher
     */
    protected void changeFrostQty(Voucher voucher, String remarks) {
        voucher.getVoucherItems().forEach(
                voucherItem -> {
                    VoucherInventory voucherInventory = voucherInventoryRepository.findByVoucherItem(voucherItem).stream().findAny().orElseThrow(() -> new RuntimeException("找不到批次信息！"));
                    InventoryBatch inventoryBatch = voucherInventory.getInventoryBatch();

                    // 冻结批次数量
                    inventoryService.changeFrostQty(inventoryBatch, inventoryBatch.getUom(), inventoryBatch.getPurchaseQty(),
                            voucher.getCompany(), voucher.getInnerBusinessType(), voucher.getId(),
                            String.valueOf(voucherItem.getId()), remarks);
                });
    }

    /**
     * 发送事件回写方案的数据
     *
     * @param voucher 凭证信息
     */
    protected void sendServicePlanBathAndSupplier(Voucher voucher) {
        List lists = voucher.getVoucherItems().stream()
                .map(voucherItem -> {
                    VoucherInventory voucherInventory = voucherInventoryRepository.findByVoucherItem(voucherItem)
                            .stream().findAny().orElseThrow(() -> new RuntimeException("找不到批次信息！"));
                    InventoryBatch inventoryBatch = voucherInventory.getInventoryBatch();

                    // 冻结批次数量
                    inventoryService.changeFrostQty(inventoryBatch, inventoryBatch.getUom(), inventoryBatch.getPurchaseQty(),
                            voucher.getCompany(), voucher.getInnerBusinessType(), voucher.getId(), String.valueOf(voucherItem.getId()), "发送事件回写方案的数据");
                    return MapUtil.mapper("servicePlanItemId", voucherItem.getOriginItemId(),
                            "supplierId", voucher.getPartner().getId(), "batchId", inventoryBatch.getId(),
                            "qty", voucherItem.getProductQty(), "classification", voucher.getClassification(), "paintPrice", voucherItem.getPriceUnit());
                }).collect(Collectors.toList());

        sendSynEvent("event:ser.serverPlanItem.setBatchAndSupplier", lists);
    }

    /**
     * 零售明细回写批次信息, 冻结批次数量
     *
     * @param retailOrderItems 零售单明细
     * @param voucher          凭证
     */
    protected void sendRetailBathAndSupplier(List<RetailOrderItem> retailOrderItems, Voucher voucher) {
        if (retailOrderItems.isEmpty()) return;

        String orderId = retailOrderItems.stream().findFirst().get().getOrder().getId();
        RetailOrder retailOrder = SpringManager.getBean(RetailOrderRepository.class).findOne(orderId);
        RetailOrder order = Optional.of(retailOrder).orElseThrow(() -> new RuntimeException(String.format("零售明细回写批次信息, 冻结批次数量时找不到主表[%s]", orderId)));

        Map<String, VoucherItem> voucherItemMap = voucher.getVoucherItems().stream().collect(Collectors.toMap(VoucherItem::getOriginItemId, x -> x));
        order.getSaleItems().stream().filter(retailOrderItems::contains).forEach(
                item -> {
                    if (!voucherItemMap.containsKey(item.getId())) throw new RuntimeException("找不到凭证明细对应！");
                    VoucherItem voucherItem = voucherItemMap.get(item.getId());
                    VoucherInventory voucherInventory = voucherInventoryRepository.findByVoucherItem(voucherItem)
                            .stream().findAny().orElseThrow(() -> new RuntimeException("找不到批次信息！"));
                    InventoryBatch inventoryBatch = voucherInventory.getInventoryBatch();

                    // 冻结批次数量
                    inventoryService.changeFrostQty(inventoryBatch, inventoryBatch.getUom(), inventoryBatch.getPurchaseQty(),
                            voucher.getCompany(), voucher.getInnerBusinessType(), voucher.getId(),
                            String.valueOf(voucherItem.getId()), "带安和服务商品零售处理 零售明细回写批次信息, 冻结批次数量");

                    item.setInventoryBatch(inventoryBatch);
                    item.setSupplier(voucherInventory.getInventorySupplier());
                    if (VoucherType.PAINT_PRODUCT.equals(voucher.getClassification())) {
                        item.setSupplier(voucherInventory.getInventorySupplier());
                        item.setPaintFlag(true);
                    }

                });
        SpringManager.getBean(RetailOrderRepository.class).save(order);
    }


    /**
     * 分销单会写批次与供应商
     *
     * @param voucher
     */
    protected void sendSaleBathAndSupplier(Voucher voucher) {
        List lists = voucher.getVoucherItems().stream()
                .map(voucherItem -> {
                    VoucherInventory voucherInventory = voucherInventoryRepository.findByVoucherItem(voucherItem).stream().findAny().orElseThrow(() -> new RuntimeException("找不到批次信息！"));
                    InventoryBatch inventoryBatch = voucherInventory.getInventoryBatch();

                    inventoryService.changeFrostQty(inventoryBatch, inventoryBatch.getUom(), inventoryBatch.getPurchaseQty(), voucher.getCompany(), voucher.getInnerBusinessType(), voucher.getId(), String.valueOf(voucherItem.getId()), "带安/服务/油漆商品生成分销冻结批次");
                    // 单独处理油漆供应
                    String supplierId = voucher.getPartner().getId();
                    if (VoucherType.PAINT_PRODUCT.equals(voucher.getClassification()))
                        supplierId = voucherItem.getSupplier().getId();

                    return MapUtil.mapper("id", voucherItem.getOriginItemId(), "supplierId", supplierId, "batchId", inventoryBatch.getId(),
                            "classification", voucher.getClassification(), "priceUint", voucherItem.getPriceUnit());
                }).collect(Collectors.toList());
        sendSynEvent("event:saleOrder.setBatchAndSupplier", MapUtil.mapper("id", voucher.getSource(), "items", lists));
    }

    protected void createInvoiceAndFixOriginNumber(RetailOrder retailOrder, Voucher voucher) {
        // 第一步：获取 invoice Mapping 文件
        Map m = invoke("voucher.flow.invoice", MapUtil.mapped(voucher));

        // 第二步：修改 origin 单号
        if ("server".equals(retailOrder.getOrderType()) || LogicalUtil.in(retailOrder.getScene().getId(), "RO002", "RO003")) {
            // 服务来源的零售单 + 定损场景
            m.put("origin", retailOrder.getSource());
            m.put("originBusinessType", retailOrder.getSourceBusinessType());
        }

        // 第三步：生成账单
        invoke("invoice.create", m);
    }

    /**
     * 分销单产生的数据进入这里的只有下面判断的两种场景
     *
     * @param saleOrder 分销单
     * @param voucher   业务凭证
     */
    protected void createInvoiceAndFixOriginNumber(SaleOrder saleOrder, Voucher voucher) {
        Map m = invoke("voucher.flow.invoice", MapUtil.mapped(voucher));
        if ("INNER_SALE".equals(saleOrder.getOrderType())) {
            // 内协来源：基地服务方案号
            m.put("origin", saleOrder.getSource());
            m.put("originBusinessType", saleOrder.getSourceBusinessType());
        } else {
            // 定损来源：定损报价单号
            RetailOrder retailOrder = SpringManager.getBean(RetailOrderRepository.class).findOne(saleOrder.getSource());
            m.put("origin", retailOrder.getSource());
            m.put("originBusinessType", retailOrder.getSourceBusinessType());
        }
        invoke("invoice.create", m);
    }
}
